package logger

import (
	"strconv"
)

type FormatterJson struct {
	PrefixLikeMap bool
}

func (f *FormatterJson) Begin(ctx *Context) {
	ctx.Buffer().WriteString("{")
}

func (f *FormatterJson) End(ctx *Context) {
	ctx.Buffer().WriteString("}")
}

func (f *FormatterJson) AppendTimeBytes(ctx *Context, bs []byte) {
	ctx.Buffer().WriteString(`"time":"`)
	ctx.Buffer().Write(bs)
	ctx.Buffer().WriteByte('"')
}

func (f *FormatterJson) AppendLevel(ctx *Context, lv Level) {
	ctx.Buffer().WriteString(`,"level":"`)
	ctx.Buffer().WriteString(lv.String())
	ctx.Buffer().WriteByte('"')
}

func (f *FormatterJson) PrefixBegin(ctx *Context) {
	if f.PrefixLikeMap {
		ctx.Buffer().WriteString(`,"prefix":{`)
	} else {
		ctx.Buffer().WriteString(`,"prefix":[`)
	}
}

func (f *FormatterJson) PrefixEnd(ctx *Context) {
	if f.PrefixLikeMap {
		ctx.Buffer().WriteByte('}')
	} else {
		ctx.Buffer().WriteByte(']')
	}
}

func (f *FormatterJson) AppendPrefix(ctx *Context, index int, pre string) {
	if index > 0 {
		ctx.Buffer().WriteByte(',')
	}
	if f.PrefixLikeMap {
		ctx.Buffer().WriteString(`"`)
		ctx.Buffer().WriteString(strconv.Itoa(index))
		ctx.Buffer().WriteString(`":`)
		ctx.Buffer().WriteString(`"`)
		ctx.Buffer().WriteString(pre)
		ctx.Buffer().WriteByte('"')
	} else {
		ctx.Buffer().WriteString(`"`)
		ctx.Buffer().WriteString(pre)
		ctx.Buffer().WriteByte('"')
	}
}

func (f *FormatterJson) FieldBegin(ctx *Context) {
	ctx.Buffer().WriteString(`,"field":{`)
}

func (f *FormatterJson) FieldEnd(ctx *Context) {
	ctx.Buffer().WriteByte('}')
}

func (f *FormatterJson) AppendFieldInt64(ctx *Context, index int, k string, v int64) {
	if index > 0 {
		ctx.Buffer().WriteByte(',')
	}
	ctx.Buffer().WriteString(`"`)
	ctx.Buffer().WriteString(k)
	ctx.Buffer().WriteString(`":`)
	bs := strconv.AppendInt(ctx.Buffer().AvailableBuffer(), v, 10)
	ctx.Buffer().Write(bs)
}

func (f *FormatterJson) AppendFieldUint64(ctx *Context, index int, k string, v uint64) {
	if index > 0 {
		ctx.Buffer().WriteByte(',')
	}
	ctx.Buffer().WriteString(`"`)
	ctx.Buffer().WriteString(k)
	ctx.Buffer().WriteString(`":`)
	bs := strconv.AppendUint(ctx.Buffer().AvailableBuffer(), v, 10)
	ctx.Buffer().Write(bs)
}

func (f *FormatterJson) AppendFieldFloat64(ctx *Context, index int, k string, v float64) {
	if index > 0 {
		ctx.Buffer().WriteByte(',')
	}
	ctx.Buffer().WriteString(`"`)
	ctx.Buffer().WriteString(k)
	ctx.Buffer().WriteString(`":`)
	bs := strconv.AppendFloat(ctx.Buffer().AvailableBuffer(), v, 'f', -1, 64)
	ctx.Buffer().Write(bs)
}

func (f *FormatterJson) AppendFieldString(ctx *Context, index int, k string, v string) {
	if index > 0 {
		ctx.Buffer().WriteByte(',')
	}
	ctx.Buffer().WriteString(`"`)
	ctx.Buffer().WriteString(k)
	ctx.Buffer().WriteString(`":"`)
	ctx.Buffer().WriteString(v)
	ctx.Buffer().WriteByte('"')
}

func (f *FormatterJson) AppendMessage(ctx *Context, msg string) {
	ctx.Buffer().WriteString(`,"msg":"`)
	ctx.Buffer().WriteString(msg)
	ctx.Buffer().WriteByte('"')
}

var FormatterJson_ErrorPrefix = `,"error":"`

func (f *FormatterJson) AppendError(ctx *Context, err error) {
	ctx.Buffer().WriteString(FormatterJson_ErrorPrefix)
	ctx.Buffer().WriteString(err.Error())
	ctx.Buffer().WriteByte('"')
}

func (f *FormatterJson) AppendCodeLine(ctx *Context, file string, line int) {
	ctx.Buffer().WriteString(`,"file":"`)
	ctx.Buffer().WriteString(file)
	ctx.Buffer().WriteString(`:`)
	bs := strconv.AppendInt(ctx.Buffer().AvailableBuffer(), int64(line), 10)
	ctx.Buffer().Write(bs)
	ctx.Buffer().WriteByte('"')
}
